#include "p2head.h"

extern Lock waitingRoomLock;
extern Lock nLock;
extern Lock wrnLock;
extern Lock nwLock;	//lock of nurse and waiting room nurse
extern Lock nwwLock;
extern Lock exRoomLock;
extern Lock* roomLock[6];
extern Condition* roomCondition[6];
extern Condition waitingRoomCondition;
extern Condition wrnWaiting;
extern Condition nurseWaiting; //CV for patient and nurse
extern Condition nwCondition;
extern Condition nwwCondition;
extern Condition exRoomCondition;
extern waitingRoomMoitor WRM;
extern examinationRoomMoitor erm;
extern Lock nurseLock;
extern Condition nurseCondition;
extern doctorOfficeMonitor dom;
extern Lock* doctorLock[4];
extern Condition* doctorCondition[4];
extern doctorOfficeMonitor* doctoroffice[4];
extern struct examSheet* wallpoket[7];
extern Lock wallpoketLock;
extern bool nursemv[6];
extern bool *patientmv;
extern bool doctormv[6];
extern int test;
extern int parentchildNumber;
extern int adultpatientNumber;


/***********************************xray room*********************************/
extern int xrayroom[3];
extern List* xrayInQueue;	// sheetqueue wait for the xray(wallpocketIn)
extern List* xrayOutQueue;	// sheetqueue of done 
extern int xrayInCount;	//number of patient who is waiting for the xray
extern int xrayOutCount;	//number of patient who has finished the xray

//Lock and CVs for xray room
extern Lock* xrayLock[3];
extern Condition* xrayCondition[3];
extern Lock xraycheck;
//nurse gives sheet to xraytechnician
extern struct examSheet* xraysheet[3];	

//for interaction of nurse and patient in the xray waiting room
extern Lock xrayOutLock;		
extern Condition xrayOutC;	
extern Lock xrayInLock;
extern Condition xrayInC;
extern int doctorNumber;
extern int technicianNumber;
extern Lock cabinetLock;
extern int testcontrol;

int exroomcheck(){	//check available room numbers.
	int num;
	exRoomLock.Acquire();
	for(num=1;num<6;num++){
		if(erm.exRoom[num]==1){
			erm.exRoom[num]=0;
			exRoomLock.Release();
			return num;
		}
	}//end of for
	exRoomLock.Release();
	return num;
}

void nurse(int which){
	int i=0;
	int y;
	int exNum;	//remember the examination room number
	int d;
	int wnum; //wall pocket number
	int x;
	int over=0;
	
	struct examSheet* np;
	int nTask=0; //0=FREE 1=get a patient from waiting room. 2= check the patient 3= escort to X-RAY 
			     //4= escort back wo exroom 5=shot 6=escort to cashier 7. check wall pockets
			   
	while(true){
		//wake up a patient to the examination room
		if(nTask==0){
			exNum=exroomcheck();
			if(exNum!=6)	//there is a room available
				nTask=1;
			else 
				nTask=7;
		}//end of if

		for(y=0;y<10;y++)
			currentThread->Yield(); //release the CPU
		
		if(nTask==1){		//get a patient from waiting room
			waitingRoomLock.Acquire();
			if(WRM.wrnStatus==1){ //waiting room nurse is free
				WRM.wrnStatus=0;	//make WRN busy
				waitingRoomLock.Release();
				wrnLock.Acquire();
				WRM.wrnTask=2;
				wrnWaiting.Signal(&wrnLock);		
				wrnWaiting.Wait(&wrnLock);			//wait for the nurse's response
				if(WRM.nsheet==NULL){
					wrnWaiting.Signal(&wrnLock);		//tell the waiting room nurse I get the sheet.
					//release the exroom					
					exRoomLock.Acquire();
					erm.exRoom[exNum]=1;
					exRoomLock.Release();
					nTask=7; //done
				}
				else{						
					if(testcontrol==7)
						printf("Nurse [%d] tells Waiting Room Nurse to give a new examination sheet.\n", which);
					np=WRM.nsheet;
					np->exRoomNum=exNum;
					WRM.nurseid=which;
					wrnWaiting.Signal(&wrnLock);		//tell the waiting room nurse I get the sheet.

					while(true){
						if(patientmv[np->name]==false)
							currentThread->Yield();
						else break;
					}
					
					nLock.Acquire();
					nurseWaiting.Signal(&nLock);
					WRM.sheet = np;	//let patient know the sheet
					WRM.nurseid = which;

					nLock.Release();
					nTask=2;
				}//end of lese

				wrnLock.Release();
			}
			else{	//waitingroomnurse is busy.
				waitingRoomLock.Release();
				nwLock.Acquire();
				WRM.nurseWaitingCount++;
				nwCondition.Wait(&nwLock);	//waiting for the response of WRN
				nwLock.Release();

				nwwLock.Acquire();
				if(WRM.nsheet==NULL){
					exRoomLock.Acquire();
					erm.exRoom[exNum]=1;
					exRoomLock.Release();
					nTask=7; //done
				}
				else{					
					if(testcontrol==7)
						printf("Nurse [%d] tells Waiting Room Nurse to give a new examination sheet.\n", which);
					np=WRM.nsheet;
					np->exRoomNum=exNum;

					while(true){
						if(patientmv[np->name]==false)
							currentThread->Yield();
						else break;
					}
					
					nLock.Acquire();
					nurseWaiting.Signal(&nLock);	//wake up a patient
					WRM.sheet = np;	//let patient know the sheet		
					WRM.nurseid = which;
					nLock.Release();
					nTask=2;
				}
				WRM.nurseid=which;
				nwwCondition.Signal(&nwwLock);	//tell the nurse i got the sheet.
				nwwLock.Release();
			}

		}


		if(nTask==2){		//check the patient in the exroom
			
			//wait for the response of patient			
			roomLock[np->exRoomNum]->Acquire();
			
			if(testcontrol==1||testcontrol==7||testcontrol==4)
				if(np->patientType==1)
					printf("Nurse [%d] escorts Adult Patient [%d] to the examination room [%d].\n",which,np->name,np->exRoomNum);
				else
					printf("Nurse [%d] escorts Adult Parent [%d] to the examination room [%d].\n",which,np->name,np->exRoomNum);

			nursemv[which]=true;	//waiting room nurse get ready to wait.
			roomCondition[np->exRoomNum]->Wait(roomLock[np->exRoomNum]);
			nursemv[which]=false;
			
			
			/**********************check the patient************************/
			
			if(testcontrol==7)
				if(np->patientType==1)
					printf("Nurse [%d] takes the temperature and blood pressure of Adult Patient [%d].\n",which,np->name);
				else			
					printf("Nurse [%d] takes the temperature and blood pressure of Adult Parent [%d].\n",which,np->name);				if(testcontrol==1||testcontrol==7||testcontrol==4)

			if(testcontrol==7)
				if(np->patientType==1)
					printf("Nurse [%d] asks Adult Patient [%d] what Symptoms do you have?\n",which,np->name);
				else
					printf("Nurse [%d] asks Adult Parent [%d] what Symptoms do you have?\n",which,np->name);

			(*roomCondition[exNum]).Signal(roomLock[exNum]);
			(*roomCondition[exNum]).Wait(roomLock[exNum]);
			strcpy(np->symptom,erm.symptom[exNum]); //get symptom from patient

			
			if(testcontrol==7)
				if(np->patientType==1)
					printf("Nurse [%d] writes all the information of Adult Patient [%d] in his examination sheet.\n",which,np->name);
				else
					printf("Nurse [%d] writes all the information of Adult Parent [%d] in his examination sheet.\n",which,np->name);

			roomLock[np->exRoomNum]->Release();			
			nTask=5;
		}

		for(y=0;y<10;y++)
			currentThread->Yield(); //release the CPU

		if(nTask==3){			//go to xray-room		
			//roomLock[np->exRoomNum]->Acquire();
			//roomCondition[np->exRoomNum]->Signal(roomLock[np->exRoomNum]);	//inform the patient						
			//roomLock[np->exRoomNum]->Release();
			
			xraycheck.Acquire();		
			for(x=1;x<(technicianNumber+1);x++){
				if(xrayroom[x]==1){
					xrayroom[x]=0;		//make this technician busy
					break;
				}	
			}
			xraycheck.Release();
			
			roomLock[np->exRoomNum]->Acquire();
			np->xrayroom=x;
			roomCondition[np->exRoomNum]->Signal(roomLock[np->exRoomNum]);	//inform the patient						
			roomLock[np->exRoomNum]->Release();
						
			if(x==(technicianNumber+1)){		//no xray room is available
				//drop the patient and put the sheet in the wallpocket

				//xrayInQueue->Append((void*)np);
				
				if(testcontrol==4||testcontrol==7)
					if(np->patientType==1)
						printf("Nurse [%d] escorts Adult Patient [%d] to the X-ray room .\n",which,np->name);
					else
						printf("Nurse [%d] escorts Adult Parent [%d] to the X-ray room .\n",which,np->name);

				if(testcontrol==7)
					if(np->patientType==1)
						printf("Nurse [%d] informs X-Ray Technician about Adult Patient [%d] and hands over the examination sheet.\n",which,np->name);
					else
						printf("Nurse [%d] informs X-Ray Technician about Child Patient [%d] and hands over the examination sheet.\n",which,np->name);
				
				if(testcontrol==1||testcontrol==7||testcontrol==4)
					printf("Nurse [%d] leaves the X-ray Room.\n",which);
			}
			else{
				if(testcontrol==4||testcontrol==7)
					if(np->patientType==1)
						printf("Nurse [%d] escorts Adult Patient [%d] to the X-ray room [%d].\n",which,np->name,x);
					else
						printf("Nurse [%d] escorts Adult Parent [%d] to the X-ray room [%d].\n",which,np->name,x);
				
				if(testcontrol==7)
					if(np->patientType==1)
						printf("Nurse [%d] informs X-Ray Technician [%d] about Adult Patient [%d] and hands over the examination sheet.\n",which,x,np->name);
					else
						printf("Nurse [%d] informs X-Ray Technician [%d] about Child Patient [%d] and hands over the examination sheet.\n",which,x,np->name);

				xrayLock[x]->Acquire();
				xraysheet[x]=np;
				//give the sheet to the technician
				np->xrayroom=x;
				xrayCondition[x]->Signal(xrayLock[x]);		//inform the technician
				xrayCondition[x]->Wait(xrayLock[x]);		//make sure the technician get the sheet
				xrayLock[x]->Release();
				
				if(testcontrol==7)
					printf("Nurse [%d] leaves the X-ray Room [%d].\n",which,x);
			}	
			nTask=0;
		}
			
		if(nTask==4){		//give patient a shot
			
			if(testcontrol==7)
				if(np->patientType==1)
					printf("Nurse [%d] goes to supply cabinet to give to take medicine for Adult Patient [%d].\n",which, np->name);
				else
					printf("Nurse [%d] goes to supply cabinet to give to take medicine for Parent [%d].\n",which, np->name);
			roomLock[np->exRoomNum]->Acquire();
			cabinetLock.Acquire();
			//printf("Using the cabinet\n");
			cabinetLock.Release();
			
			if(testcontrol==7)
				if(np->patientType==1)
					printf("Nurse [%d] asks Adult Patient [%d] \"Are you ready for the shot?\"\n",which,np->name);
				else
					printf("Nurse [%d] asks Parent [%d] \"Are you ready for the shot?\"\n",which,np->name);
			
			roomCondition[np->exRoomNum]->Signal(roomLock[np->exRoomNum]);
			roomCondition[np->exRoomNum]->Wait(roomLock[np->exRoomNum]);

			roomCondition[np->exRoomNum]->Signal(roomLock[np->exRoomNum]);
			
			if(testcontrol==7)
				if(np->patientType==1)
					printf("Nurse [%d] tells Adult Patient/Parent [%d] \"Your shot is over.\"\n",which,np->name);
				else
					printf("Nurse [%d] tells Adult Patient/Parent [%d] \"Your shot is over.\"\n",which,np->name);

			
			roomCondition[np->exRoomNum]->Wait(roomLock[np->exRoomNum]);
			
			roomLock[np->exRoomNum]->Release();
			

			nTask=5;
		}

		for(y=0;y<10;y++)
			currentThread->Yield(); //release the CPU
			
		if(nTask==5){		//call a doctor

			doctorLock[0]->Acquire();
			for(d=1;d<(doctorNumber+1);d++){
				if(dom.doctorstatus[d]==1){
					dom.doctorstatus[d]=0;
					break;
				}
			}
			doctorLock[0]->Release();
			
			if(d==(doctorNumber+1)){
				nurseLock.Acquire();
				dom.nurseCount++;
				nurseCondition.Wait(&nurseLock);
				nurseLock.Release();
				doctorLock[0]->Acquire();
				for(d=1;d<doctorNumber+1;d++){
					if(dom.doctorstatus[d]==1){
						dom.doctorstatus[d]=0;
						break;
					}
				}
				doctorLock[0]->Release();
			}
			
			if(testcontrol==7)
				if(np->patientType==1)
					printf("Nurse [%d] informs Doctor [%d] that Adult Patient [%d] is waiting in the examination room [%d].\n",which,d,np->name,np->exRoomNum);	
				else
					printf("Nurse [%d] informs Doctor [%d] that Child Patient [%d] is waiting in the examination room [%d].\n",which,d,np->name,np->exRoomNum);	

			while(true){
				if(doctormv[d]==false)
					currentThread->Yield();
				else 
					break;	
			}
			
			doctorLock[d]->Acquire();
			doctoroffice[d]->roomNumber=np->exRoomNum;
			doctoroffice[d]->sheet=np;
			doctorCondition[d]->Signal(doctorLock[d]);
			doctorLock[d]->Release();			
			
			if(testcontrol==7)
				if(np->patientType==1)
					printf("Nurse [%d] hands over to the Doctor [%d] the examination sheet of Adult Patient [%d].\n",which,d,np->name);	
				else
					printf("Nurse [%d] hands over to the Doctor [%d] the examination sheet of Child Patient [%d].\n",which,d,np->name);	
			nTask=0;
			
		}

		if(nTask==6){		//escrot patient back to the examination room
			//get the sheet
			
			np=(struct examSheet*)xrayOutQueue->Remove();
			//wake up the patient
			//xrayOutLock.Acquire();
			xrayOutCount--;
			xrayOutC.Signal(&xrayOutLock);			
			xrayOutLock.Release();
			
			if(testcontrol==1||testcontrol==7||testcontrol==4)
				if(np->patientType==1)
					printf("Nurse [%d] escorts Adult Patient [%d] to the examination room [%d].\n",which,np->name,np->exRoomNum);
				else
					printf("Nurse [%d] escorts Adult Parent [%d] to the examination room [%d].\n",which,np->name,np->exRoomNum);
			
			//look up whether a short is needed
			if(np->shot==1){
				nTask=4;
			}
			else
				nTask=5;			
		}		

		for(y=0;y<10;y++)
			currentThread->Yield(); //release the CPU
			
		if(nTask==7){		//check wall pocket	and make decision	
			wallpoketLock.Acquire();
			for(wnum=1;wnum<6;wnum++){
				if(wallpoket[wnum]!=NULL){
					np=wallpoket[wnum];
					
					if(testcontrol==7)
						printf("Nurse [%d] checks the wall box of examination room [%d].\n",which,wnum);
					if(np->status==0||(np->shot==0&&np->xray==0)){
						//bing the patient to the cashier
						
						if(testcontrol==1||testcontrol==7||testcontrol==4)
							if(np->patientType==1)
								printf("Nurse [%d] escorts Adult Patient [%d] to Cashier.\n",which,np->name);
							else
								printf("Nurse [%d] escorts Parent [%d] to Cashier.\n",which,np->name);
							
						roomLock[wnum]->Acquire();
						roomCondition[wnum]->Signal(roomLock[wnum]);	
						exRoomLock.Acquire();
						wallpoket[wnum]=NULL;		
						erm.exRoom[wnum]=1;
						roomLock[wnum]->Release();
						exRoomLock.Release();
						
						nTask=0;
						break;
					}
					else if(np->xray!=0){ 	//escort patient to Xray room
						nTask=3;
						roomLock[wnum]->Acquire();			
						np->status=2;	//for doctor to check
						roomLock[wnum]->Release();
						wallpoket[wnum]=NULL;
						break;
					}
					else if(np->shot==1){	//give patient a shot
						nTask=4;
						roomLock[wnum]->Acquire();			
						np->status=2;	//for doctor to check
						roomLock[wnum]->Release();
						wallpoket[wnum]=NULL;
						break;
					}
				}
			}
			wallpoketLock.Release();
			if(wnum==6){	//no sheets in wallpockets
				//check the xrayroom
				xrayOutLock.Acquire();
				if(xrayOutCount>0){					
					nTask=6;
				}
				else{			//no patient is done
					xrayOutLock.Release();
					nTask=0;
				}	
			}	

			if(test == parentchildNumber+adultpatientNumber)
				break;
		}
	}//end of while	
	
	//end of while
}



